<script setup>
import { onMounted, reactive, ref, unref } from 'vue';

let wrapWidth = 0;
let contentWidth = 0;
const content = ref(null)
const wrapper = ref(null)
const state = reactive({
  offset: 0, 
  duration: 0
})

const raf = (fn) => {
  return requestAnimationFrame(fn)
}


// double raf for animation
const doubleRaf = (fn) =>  {
  raf(() => raf(fn));
}

const onTransitionEnd = () => {
  state.offset = wrapWidth;
  state.duration = 0;

  raf(() => {
    // use double raf to ensure animation can start
    doubleRaf(() => {
      state.offset = -contentWidth;
      state.duration = (contentWidth + wrapWidth) / +60;
    })
  })
};

const reset = () => {
  wrapWidth = 0;
  contentWidth = 0;
  state.offset = 0;
  state.duration = 0;

  let wrapRefWidth = unref(wrapper).getBoundingClientRect().width;
  let contentRefWidth = unref(content).getBoundingClientRect().width;

  doubleRaf(() => {
    wrapWidth = wrapRefWidth;
    contentWidth = contentRefWidth;
    state.offset = -contentWidth;
    state.duration = contentWidth / +60;
  })
}

onMounted(() => {
  reset()
})
</script>

<template>
<div class="marqueen_wrapper" ref="wrapper">
    <div 
      class="marqueen_content" 
      ref="content" 
      :style="{transform: state.offset ? `translateX(${state.offset}px)` : '', transitionDuration: `${state.duration}s`,}" 
      @transitionend="onTransitionEnd"
    >
        这是一段滚动文字
    </div>
</div>
</template>

<style lang="scss" scoped>
.marqueen_wrapper {
  position: relative;
  display: flex;
  flex: 1;
  align-items: center;
  height: 40px;
  line-height: 24px;
  padding: 8px;
  overflow: hidden;
  font-size: 16px;
  background: #fff;
  .marqueen_content {
    position: absolute;
    white-space: nowrap;
    transition-timing-function: linear;
  }
}
</style>